Categories
Modern JavaScript

Best of Modern JavaScript — Control Object Operations

Spread the love

Since 2015, JavaScript has improved immensely.

It’s much more pleasant to use it now than ever.

In this article, we’ll look at metaprogramming with JavaScript proxies.

Handle Negative Array Indices

With proxies, we can enhance arrays by letting us access arrays with negative indexes.

For instance, we can write:

const handler = {
  get(target, propKey, receiver) {
    const index = Number(propKey);
    if (index < 0) {
      propKey = String(target.length + index);
    }
    return target[propKey];
  }
};

const target = [];
target.push(1, 2, 3);
const arr = new Proxy(target, handler);

console.log(arr[-1])

We create the handler object with the get method.

If we have an index that’s less than 0, then we make it positive by adding the target.length to it.

Then we return the property of array with the index of the array.

Next, we create the target array with the arguments.

Then we return a proxy which is an array-like object that we can use negative indexes with.

Setting Properties

The set method in the handler object lets us control how we set properties in an object.

For example, we can write:

function createArray(callback) {
  const array = [];
  return new Proxy(array, {
    set(target, propertyKey, value, receiver) {
      callback(propertyKey, value);
      return Reflect.set(target, propertyKey, value, receiver);
    }
  });
}
const arr = createArray(
  (key, value) => console.log(key, value));
arr.push('a');

to create an array where we can watch the operations of it.

We have a createArray function that takes a callback that’s called whenever we set a value on the array.

The callback is called with the propertyKey and value .

Then we see the array operations logged as they’re being done.

Revocable References

We can create revocable references so that we can access objects only when we’re allowed.

For example, we can write:

const target = {};
const handler = {};
const {
  proxy,
  revoke
} = Proxy.revocable(target, handler);

target is an object that we can create a proxy with.

handler is an object to let us intercept and change the object operations.

proxy is the proxy returned.

And revoke is a function that lets us revoke access to the proxy.

Meta Object

JavaScript objects have hidden properties that let us get objects.

There’s a method to let us get the object’s properties and return it.

They can trap get and call operations.

Enforcing Invariants for Proxies

We can enforce various kinds of invariants with proxies.

One thing we can do is to disable the extensibility of objects.

We can use the Object.preventExtensions method to disable adding properties to objects.

For instance, we can write:

'use strict'
const obj = Object.preventExtensions({});
obj.bar = 'foo';

to stop us from adding properties to an object.

If strict mode is on, then we get the error ‘Uncaught TypeError: Cannot add property bar, object is not extensible’ if we try to add a property to a non-extensible object.

We can check if an object is extensible by writing:

console.log(Object.isExtensible(obj));

If it returns true , then we can add properties to it.

Conclusion

We can do various things with proxies, like controlling access to an object and more.

For other operations, we don’t need proxies. The Object constructor has static methods to let us control object operations.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *